﻿using OpenCvSharp;

using System;
using System.Collections.Generic;

using Xc.DataAccess.CodeReader.Models;
using Xc.DataAccess.CodeReader.Models.Filters;
using Xc.DataAccess.CodeReader.Properties;
using Xc.DataAccess.Core;
using System.Linq;
using System.Threading.Tasks;

namespace Xc.DataAccess.CodeReader
{
    /// <summary>
    /// 图像过滤服务
    /// </summary>
    public class MatFilterService : IMatFilterService
    {
        /// <summary>
        /// 图像过滤器
        /// </summary>
        private readonly List<FilterBase> imageFilters = new List<FilterBase>();
        /// <summary>
        /// 添加过滤器
        /// </summary>
        /// <param name="imageFilter"></param>
        /// <returns></returns>
        public IMatFilterService Add(params FilterBase[] imageFilter)
        {
            imageFilters.AddRange(imageFilter);
            return this;
        }
        /// <summary>
        /// 使用结果
        /// </summary>
        /// <param name="Current"></param>
        /// <param name="mat"></param>
        /// <param name="pre"></param>
        /// <param name="FilterBases"></param>
        /// <returns></returns>
        private async Task<ResultData<Mat>> UseResult(FilterBase Current, Mat mat, FilterBase pre, FilterBase[] FilterBases= null)
        {
           return await Task.Run(async () => {
                var d = await UseBeforeResult(Current, mat, pre, FilterBases);
                if (d.IsSuccess)
                {
                    var dd = Current.Use(mat, FilterBases, pre);
                    if (dd.IsSuccess)
                    {
                        return await UseAfterResult(Current, dd.Data, Current, FilterBases);
                    }
                    else
                    {
                        return ResultData<Mat>.Reject(dd.Message, null);
                    }
                }
                else
                {
                    return ResultData<Mat>.Reject(d.Message, null);
                }
            });
            
        }
        /// <summary>
        /// 执行结果之前
        /// </summary>
        /// <param name="Current"></param>
        /// <param name="mat"></param>
        /// <param name="pre"></param>
        /// <param name="FilterBases"></param>
        /// <returns></returns>
        private async Task<ResultData<Mat>> UseBeforeResult(FilterBase Current,Mat mat,FilterBase pre, FilterBase[] FilterBases= null)
        {
            try
            {
                if (Current?.BeforeExecute != null)
                {
                    var temp = Current?.BeforeExecute?.Invoke(FilterBases, pre, mat);
                    if (temp != null)
                    {
                       return await UseResult(temp,mat,pre,FilterBases);
                    }
                }
                return ResultData<Mat>.Accept(TextResource.get_mat_successful,mat);
            }
            catch (Exception err)
            {
                return ResultData<Mat>.Reject(err.Message, null);
            }
        }
        /// <summary>
        /// 执行结果之后
        /// </summary>
        /// <param name="Current"></param>
        /// <param name="mat"></param>
        /// <param name="pre"></param>
        /// <param name="FilterBases"></param>
        /// <returns></returns>
        private async Task<ResultData<Mat>> UseAfterResult(FilterBase Current, Mat mat, FilterBase pre, FilterBase[] FilterBases = null)
        {
            try
            {
                if (Current?.AfterExecute != null)
                {
                    var cc = Current?.AfterExecute?.Invoke(FilterBases, Current, mat);
                    if (cc != null)
                    {
                        return await UseResult(cc, mat, Current, FilterBases);
                    }

                }
                return ResultData<Mat>.Accept(TextResource.get_mat_successful, mat);
            }
            catch (Exception err)
            {
                return ResultData<Mat>.Reject(err.Message, null);
            }
        }
        /// <summary>
        /// 使用过滤器开始过滤
        /// </summary>
        /// <param name="mat"></param>
        /// <returns></returns>
        public async Task<ResultData<Mat>> Use(Mat mat, FilterBase[] FilterBases=null)
        {
            Mat res = mat;
            if (FilterBases == null)
            {
                FilterBases = imageFilters.ToArray();
            }
            FilterBase preFilter =null;
            foreach (var item in FilterBases)
            {
               var d= await UseResult(item,res, preFilter,FilterBases);
                if (d.IsSuccess)
                {
                    res = d.Data;
                }
                else
                {
                    return ResultData<Mat>.Reject(d.Message, res);
                }
            }
            return ResultData<Mat>.Accept(TextResource.filter_action_complete,res);
        }
        /// <summary>
        /// 使用指定过滤器直接开始过滤
        /// </summary>
        /// <param name="mat"></param>
        /// <param name="imageFilter"></param>
        /// <returns></returns>
        public async Task<ResultData<Mat>> UseDirect(Mat mat, params FilterBase[] imageFilter)
        {
            return await Use(mat,imageFilter);
        }
        /// <summary>
        /// 清空过滤器
        /// </summary>
        public void Clear()
        {
            imageFilters.Clear();
        }
    }
}
